package com.hemerasolutions.v2trainer.model.exercise;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Transient;

import com.hemerasolutions.v2trainer.model.base.BaseModel;
import com.hemerasolutions.v2trainer.model.modality.Modality;
import com.hemerasolutions.v2trainer.util.Utility;

@Entity
public class VersionableExercise extends BaseModel {

	private static final long serialVersionUID = 1L;	
	
	@ManyToOne
	private Modality modality;

    @OneToMany(mappedBy="versionableExercise", cascade=CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval=true)
	private List<Exercise> exerciseVersions;
	
    @Transient
    Exercise exercise;
    
	public VersionableExercise() {
		super();
		this.exerciseVersions = new ArrayList<Exercise>();
		this.uuid = UUID.randomUUID().getMostSignificantBits();
	}

	public VersionableExercise(VersionableExercise other, Modality modality){
		this();
		this.modality = modality;

		for(Exercise exercise:other.exerciseVersions){
			Exercise newExercise = new Exercise(exercise,this);
			this.exerciseVersions.add(newExercise);
		}
	}

	public VersionableExercise(Modality modality) {
		this();
		this.modality = modality;
	
		this.addVersion();
	
	}

	public Exercise addVersion(){

		Exercise  exercise = new Exercise();
		exercise.setVersionableExercise(this);
		exercise.setModality(this.modality);
		exercise.setVersion(this.exerciseVersions.size() + 1);
		exercise.setCreatedAt(Utility.getRoundedDate());

		exerciseVersions.add(exercise);
		
		return exercise;
	}
	
	public VersionableExercise copy(){
		VersionableExercise copy = new VersionableExercise();
		
		copy.id = this.id; 
		copy.uuid = this.uuid;
		copy.modality = this.modality;

		for(Exercise exercise:this.exerciseVersions){
			copy.exerciseVersions.add(exercise.copy());
		}

		return copy;
	}
	
	public List<Exercise> getExerciseVersions() {
		return exerciseVersions;
	}

	public void setExerciseVersions(List<Exercise> exerciseVersions) {
		this.exerciseVersions = exerciseVersions;
	}

	public Exercise getCurrentVersion() {
		Exercise currentVersion = null;
		int version = 0;
		
		for(Exercise exercise:this.exerciseVersions){
			if(version < exercise.getVersion()){
				currentVersion = exercise;
				version = currentVersion.getVersion();
			}
		}
		return currentVersion;
	}

	public void setCurrentVersion(Exercise currentVersion) {

		for(Exercise exercise:this.exerciseVersions){
			if(exercise.getUuid() == currentVersion.getUuid()){
				exercise = currentVersion;
			}
		}		
	}

	
	public Exercise getExercise() {
		if(exercise == null){
			exercise = this.getCurrentVersion();
		}
		return exercise;
	}

	public void setExercise(Exercise exercise) {

		for(int x = 0; x < this.exerciseVersions.size(); x++){
			if(exercise.getUuid() == this.exerciseVersions.get(x).getUuid()){
				this.exerciseVersions.set(x,exercise);
			}
		}
	}

	public Modality getModality() {
		return modality;
	}

	public void setModality(Modality modality) {
		this.modality = modality;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result
				+ ((modality == null) ? 0 : modality.hashCode());
		result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		VersionableExercise other = (VersionableExercise) obj;
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		if (modality == null) {
			if (other.modality != null) {
				return false;
			}
		} else if (!modality.equals(other.modality)) {
			return false;
		}
		if (uuid == null) {
			if (other.uuid != null) {
				return false;
			}
		} else if (!uuid.equals(other.uuid)) {
			return false;
		}
		return true;
	}

	@Override
	public String toString() {
		return "VersionableExercise [exerciseVersions=" + exerciseVersions
				+ ", uuid=" + uuid + "]";
	}
}
